/*
 * CommerceSessionFinalizer.java
 *
 * Created on July 30, 2001, 11:38 AM
 */

/*
(C) Copyright MarketLive. 2006. All rights reserved.
MarketLive is a trademark of MarketLive, Inc.
Warning: This computer program is protected by copyright law and international treaties.
Unauthorized reproduction or distribution of this program, or any portion of it, may result
in severe civil and criminal penalties, and will be prosecuted to the maximum extent
possible under the law.
*/


package com.marketlive.biz.session.context;


import java.util.Vector;
import java.util.Enumeration;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.marketlive.biz.session.context.ICommerceSession;

/**
 * CommerceSessionFinalizer is responsible for execution of
 * all the processes (ISessionCommand instances) to executed
 * at the time a commerce session times out or is distroyed by
 * the garbage collector.
 * <p/>
 * According to this design a session can be finalized only once for
 * the session duration. Field "finalized" used to keep track of this.
 * NOTE: In the multi-server environment we might have to re-evaluate this.
 * <p/>
 * Note that this class is accessible only within this package.
 *
 * @author elena
 */
public class CommerceSessionFinalizer {
    
    private static Log logger = LogFactory.getLog(CommerceSessionFinalizer.class);

    /**
     * List of instances of ISessionCommand.
     * This commands will be run finalizeSession() is called.
     */
    Vector commands_;

    /**
     * Creates  a new CommerceSessionFinalizer with an empty list of commands
     */
    public CommerceSessionFinalizer() {
        commands_ = new Vector();
    }

    /**
     * Adds command to the list of commands to be run when the
     * session is finalized or timed out.
     */
    public void registerCommand(ISessionCommand command) {
        commands_.addElement(command);
    }

    /**
     * Removes command from the list of commands to be run when
     * the session is finalized or timed out.
     */
    public void unregisterCommand(ISessionCommand command) {
        commands_.remove(command);
    }

    /**
     * Executes all the commands registered to run at the
     * time of the CommerceSession object finalization or
     * when the session times out.
     */
    public void finalizeSession(ICommerceSession session) throws Exception {
        ISessionCommand command = null;
        Exception error = null;

        // execute final commands
        for (Enumeration enumeration = commands_.elements(); enumeration.hasMoreElements();) {
            command = (ISessionCommand) enumeration.nextElement();
            try {
                if (command.run(session) == ISessionCommand.FATAL_ERROR) {
                    error = new Exception(" CommerceSessionFinalizer: Error running command: " + command.getName());
                }
            } catch (Exception e) {
                error = e;
            }
        }

        // log the latest exception thrown by final commands
        if (error != null) throw error;
    }

    public void finalizeSessionForSessionSummary(ICommerceSession session) throws Exception {
        ISessionCommand command = null;
        Exception error = null;

// execute final commands
        for (Enumeration enumeration = commands_.elements(); enumeration.hasMoreElements();) {
            command = (ISessionCommand) enumeration.nextElement();
            logger.info(" Session Finalizer Running command " + command.getName());
            if (command.getName().equals("Update Session Summary")) {
                try {
                    if (command.run(session) == ISessionCommand.FATAL_ERROR) {
                        error = new Exception(" CommerceSessionFinalizer: Error running command: " + command.getName());
                    }
                } catch (Exception e) {
                    error = e;
                    logger.warn("Error finalizing commerce session" + session.getId(), e);
                }
            }
        }

// log the latest exception thrown by final commands
        if (error != null) throw error;
    }

    public void finalizeSessionOtherThanSessionSummary(ICommerceSession session) throws Exception {
        ISessionCommand command = null;
        Exception error = null;

// execute final commands
        for (Enumeration enumeration = commands_.elements(); enumeration.hasMoreElements();) {
            command = (ISessionCommand) enumeration.nextElement();
            logger.info(" Session Finalizer Running command " + command.getName());
            if (!command.getName().equals("Update Session Summary")) {
                try {
                    if (command.run(session) == ISessionCommand.FATAL_ERROR) {
                        error = new Exception(" CommerceSessionFinalizer: Error running command: " + command.getName());
                    }
                } catch (Exception e) {
                    error = e;
                    logger.warn("Error finalizing commerce session" + session.getId(), e);
                }
            }
        }

// log the latest exception thrown by final commands
        if (error != null) throw error;
    }

}
